
"""
Google Classroom backend

This file is part of polyglot, etc.
"""

import time
import datetime
import random
import json
import re
from .support import Backend, Course, ResourceCategory, ResourceRawHTML, ResourcePlain, ResourceLink, Task, FileUpload

from ..authentication import google as GoogleAuth


# From the stream -- it could map to a Task or a generic Resource depending on
# the due date, etc

class ClassroomItem:
    def __init__(self, backend, data):
        self.backend = backend
        self.data = data

        # Why are there so many IDs XXX
        self.id = self.data[0][1]

        # Nested structure
        self.double_id = self.data[0][0]

        self.name = self.data[0][5]
        self.description = self.data[0][6]

        # Due date is encoded as milliseconds since the epoch
        try:
            timestamp = self.data[1][0]
        except IndexError:
            timestamp = None

        if timestamp is not None:
            self.due_date = datetime.datetime.fromtimestamp(float(timestamp) / 1000.0)
        else:
            self.due_date = datetime.datetime.now()

        # Assign a name if there is none
        if (self.name is None) or (len(self.name) == 0):
            if (self.description is not None) and len(self.description) > 0:
                # Truncate with ellipse according to https://stackoverflow.com/questions/2872512/python-truncate-a-long-string
                self.name = self.description[:40] + (self.description[40:] and "...")
            else:
                # When all else fails :(
                self.name = self.id

        self.attachments = self.data[0][7]

    @property
    def resources(self):
        rsrcs = []

        # Query it directly for attachments and such
        did = json.dumps(self.double_id)
        query = "[[" + did + "," + did + "," + did + "," + did + "," + did + "," + did + "," + did + "," + did + "," + did + "," + did + "],[[[true,true,true,true,true,true,[true],[true,true,true,true,true,true],true,true,true,true,true,true,[true],null,null,null,true],[true,true,true,true,true,true,[true],true,null,[true,true]],[null,true]],[[true,true,true,true,true,true,[true],[true,true,true,true,true,true],true,true,true,true,true,true,[true],null,null,null,true]],[[true,true,true,true,true,true,[true],[true,true,true,true,true,true],true,true,true,true,true,true,[true],null,null,null,true],[true,true,true,true,true,true,[true],true,null,[true,true]],[true]]]]"

        info = self.backend.json_req("https://classroom.google.com/v6/streamitem/lookup", query)

        try:
            # Heck if I know
            attachments = info[0][0][1][0][2][2][0][7]
        except IndexError:
            attachments = []

        if self.description is not None:
            rsrcs += [ResourcePlain("Description", self.description)]

        for attachment in attachments:
            name = attachment[0]
            id = attachment[2]
            mimetype = attachment[4]
            link = attachment[6]

            # We can spit out the bare link if we need to
            # But for Google Drive, it pays to transform first

            if link.startswith("https://drive.google.com"):
                # Check the mimetype and proceed accordingly

                if mimetype == "application/vnd.google-apps.kix":
                    # A google doc
                    link = "https://docs.google.com/document/d/" + id + "/edit"
                else:
                    # For general Google Drive, use the raw download link. This
                    # might incur an extra auth. TODO: Have our session do the
                    # fetch

                    link = "http://drive.google.com/uc?id=" + id + "&export=download"

            # Once transformed, just spit it out as a link
            rsrcs += [ResourceLink(name, link)]

        return rsrcs

class ClassroomTask(Task):
    def __init__(self, item):
        self.item = item
        self.name = self.item.name
        self.due_date = self.item.due_date

    @property
    def resources(self):
        return self.item.resources

class ClassroomModule(ResourceCategory):
    def __init__(self, item):
        self.item = item
        self.name = self.item.name

    @property
    def children(self):
        return self.item.resources

class ClassroomCourse(Course):
    def __init__(self, backend, data):
        self.backend = backend

        # Course ID unique within this backend but not necessarily in general
        self.id = data["id"]

        # Course name and teacher name, no localisation?
        self.title = data["title"]
        self.teacher = data["teacher"]
        self.grade_summary = None

    # String of milliseconds since epoch
    def format_time(self, dt):
        return str(int(time.mktime(dt.timetuple()) * 1000) )

    # A similar endpoint is used for grabbing _all_ modules versus just the due ones

    def get_assignments(self, active):
        if active:
            # Assignment fetching is by timestamp of the due date
            time_begin = self.format_time(datetime.datetime.now())
            time_end = self.format_time(datetime.datetime.now() + datetime.timedelta(weeks=1))

            stream_item_query = "[[3,null,1],[[[true,true,true,true,true,true,null,[true,true,true,true,true,true],true,true,true,true,true,true,[true],null,null,null,true],[true,true,true,true,true,true,[true],true,null,[true,true]],[null,true]],[[true,true,true,true,true,true,null,[true,true,true,true,true,true],true,true,true,true,true,true,[true],null,null,null,true]],[[true,true,true,true,true,true,null,[true,true,true,true,true,true],true,true,true,true,true,true,[true],null,null,null,true],[true,true,true,true,true,true,[true],true,null,[true,true]],[true]]],[[[],[[" + str(self.id) + "]],[2,5],[],[],[[" + time_begin + "," + time_end + "]],[],[],[],null,null,[],[],[],[1,2]]]]"
        else:
            stream_item_query = '[[10,null,1],[[[true,true,true,true,true,true,null,[true,true,true,true,true,true],true,true,true,true,true,true,[true],null,null,null,true],[true,true,true,true,true,true,[true],true,null,[true,true]],[null,true]],[[true,true,true,true,true,true,null,[true,true,true,true,true,true],true,true,true,true,true,true,[true],null,null,null,true]],[[true,true,true,true,true,true,null,[true,true,true,true,true,true],true,true,true,true,true,true,[true],null,null,null,true],[true,true,true,true,true,true,[true],true,null,[true,true]],[true]]],[[[2,3],[["' + str(self.id) + '"]],[],[2],[],[],[],[],[],null,null,[],[],[],[]]]]'

        stream_items = self.backend.json_req("https://classroom.google.com/v6/streamitem/query", stream_item_query)[0][0][2]
        return [ClassroomItem(self.backend, item[-1]) for item in stream_items]

    @property
    def resources(self):
        items = self.get_assignments(active=False)
        return [ClassroomModule(item) for item in items]

    @property
    def tasks(self):
        items = self.get_assignments(active=True)
        return [ClassroomTask(item) for item in items]

class ClassroomBackend(Backend):
    Config = ["Email", "Password"]

    def login(self, config):
        out = GoogleAuth.auth(self.session, config, "https://classroom.google.com/")
        p = out.text
        self.token = self.make_token(p)

        return True

    def fast_login(self, config):
        p = self.session.get("https://classroom.google.com/")
        self.token = self.make_token(p.text)

    def make_token(self, q):
        t = re.search("//drive.google.com/picker\\\\\",null,null,null,null,null,null,null,\\\\\"([^\\\\]*)\\\\\",null,null,", q, re.MULTILINE).group(1)
        return t

    def json_req(self, endpoint, req):
        q = self.session.post(endpoint + "?_reqid=" + str(random.randint(11111, 99999)) + "&rt=j", {
            "f.req": req,
            "token": self.token
        })

        # Split off anti-JSON hijacking junk

        return json.loads(q.text.split("\n", 1)[1].strip())
 
    @property
    def courses(self):
        uq = "[[100,null,1],[true,true,null,null,true,true,true,true,[null,true,true,true,null,true,[true],null,[true],true,true],true,true,null,true,true,true,null,true,true,null,null,[true,true],true,true,true,true,null,null,false,[true,true],true,true,true,true,true,true,true,true],[[null,[[true]],[]],[],[2],[1,2],true,[]]]"
        course_resp = self.json_req("https://classroom.google.com/v6/querycourse", uq)

        courses = []

        for course in course_resp[0][0][2]:
            c_id = course[0][0]
            title = course[5]
            time = course[8]
            instructor_id = course[6][0][0]

            tr = '[[null,null,1],[true,true,null,true,null,true,null,null,true,true,true,true,null,null,true],[[null,[[null,["' + str(instructor_id) + '"]]],[]],[]]]'
            teacher_resp = self.json_req("https://classroom.google.com/v6/queryuser", tr)
            teacher = teacher_resp[0][0][2][0]
            teacher_name = teacher[1]
            teacher_email = teacher[2]
            teahcer_avatar = teacher[4]

            courses += [ClassroomCourse(self, {
                "id": c_id,
                "title": title,
                "time": time,
                "teacher": teacher_name
            })]

        return courses
